﻿using System;
using System.Runtime.InteropServices;
using ArgusLib.InteropServices;

namespace ArgusLib.FFmpeg.avutil.Interop
{
	static class Functions
	{
		static Functions()
		{
			//Log.Initialize();
		}

		/// <summary>
		/// Free a memory block which has been allocated with av_malloc(z)() or
		/// av_realloc().
		/// ptr = NULL is explicitly allowed.
		/// </summary>
		/// <param name="ptr">Pointer to the memory block which should be freed.</param>
		[DllImport(FFmpegDll.avutil, CallingConvention=FFmpegDll.CallingConvention)]
		public static extern void av_free(IntPtr ptr);

		/// <summary>
		/// Allocate an AVFrame and set its fields to default values.  The resulting
		/// struct must be freed using av_frame_free().
		/// </summary>
		/// <returns>An AVFrame filled with default values or null on failure.</returns>
		/// <remarks>
		/// This only allocates the AVFrame itself, not the data buffers. Those
		/// must be allocated through other means, e.g. with <see cref="av_frame_get_buffer"/> or
		/// manually.
		/// </remarks>
		[DllImport(FFmpegDll.avutil, CallingConvention=FFmpegDll.CallingConvention, EntryPoint = "av_frame_alloc")]
		[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ArgusMarshaler<AVAudioFrame>))]
		public static extern AVAudioFrame av_audioframe_alloc();

		/// <summary>
		/// Allocate an AVFrame and set its fields to default values.  The resulting
		/// struct must be freed using av_frame_free().
		/// </summary>
		/// <returns>An AVFrame filled with default values or null on failure.</returns>
		/// <remarks>
		/// This only allocates the AVFrame itself, not the data buffers. Those
		/// must be allocated through other means, e.g. with <see cref="av_frame_get_buffer"/> or
		/// manually.
		/// </remarks>
		[DllImport(FFmpegDll.avutil, CallingConvention = FFmpegDll.CallingConvention, EntryPoint = "av_frame_alloc")]
		[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ArgusMarshaler<AVVideoFrame>))]
		public static extern AVVideoFrame av_videoframe_alloc();

		/// <summary>
		/// Free the frame and any dynamically allocated objects in it,
		/// e.g. extended_data. If the frame is reference counted, it will be
		/// unreferenced first.
		/// </summary>
		/// <param name="frame">Frame to be freed. The pointer will be set to NULL.</param>
		[DllImport(FFmpegDll.avutil, CallingConvention=FFmpegDll.CallingConvention)]
		public static extern void av_frame_free(ref IntPtr frame);

		[DllImport(FFmpegDll.avutil, CallingConvention=FFmpegDll.CallingConvention)]
		public static extern void av_log_set_callback(
			[MarshalAs(UnmanagedType.FunctionPtr)]
			Delegates.av_log_callback callback);

		[DllImport(FFmpegDll.avutil, CallingConvention=FFmpegDll.CallingConvention)]
		public static extern AVLogLevels av_log_get_level();

		[DllImport(FFmpegDll.avutil, CallingConvention=FFmpegDll.CallingConvention)]
		public static extern void av_log_set_level(AVLogLevels avLogLevel);

		/// <summary>
		/// Allocate new buffer(s) for audio or video data.
		///
		/// The following fields must be set on frame before calling this function:
		/// - format (pixel format for video, sample format for audio)
		/// - width and height for video
		/// - nb_samples and channel_layout for audio
		///
		/// This function will fill AVFrame.data and AVFrame.buf arrays and, if
		/// necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.
		/// For planar formats, one buffer will be allocated for each plane.
		/// </summary>
		/// <param name="frame">Frame in which to store the new buffers.</param>
		/// <param name="align">Required buffer size alignment</param>
		/// <returns>0 on success, a negative AVERROR on error.</returns>
		[DllImport(FFmpegDll.avutil, CallingConvention=FFmpegDll.CallingConvention)]
		public static extern int av_frame_get_buffer(
			[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ArgusMarshaler<AVFrame>))]
			AVFrame frame, int align);
	}
}
